package com.smedi.ismedi.inmail.core.application.service.impl;

import com.smedi.ismedi.constructionproject.api.dto.response.ProjectBasicResponse;
import com.smedi.ismedi.inmail.core.application.command.MessageInfoCommand;
import com.smedi.ismedi.inmail.core.application.command.TaskRecordCommand;
import com.smedi.ismedi.inmail.core.application.service.MessageApplicationService;
import com.smedi.ismedi.inmail.core.application.service.TaskApplicationService;
import com.smedi.ismedi.inmail.core.domain.aggregatemodel.MessageRecord;
import com.smedi.ismedi.inmail.core.domain.aggregatemodel.TaskRecord;
import com.smedi.ismedi.inmail.core.domain.service.TaskDomainService;
import com.smedi.ismedi.inmail.core.port.adapter.service.PersonRemoteApi;
import com.smedi.ismedi.inmail.core.port.adapter.service.ProjectAssignmentRemoteApiService;
import com.smedi.ismedi.inmail.core.port.adapter.service.SafetyCheckRemoteApi;
import com.smedi.ismedi.notification.api.dto.request.SendSmsRequest;
import com.smedi.ismedi.notification.api.feign.RemoteSmsNotificationFeignApi;
import com.smedi.ismedi.personnel.api.dto.response.PersonResponse;
import com.smedi.ismedi.personnel.api.feign.RemotePersonCoreFeignApi;
import com.smedi.ismedi.safetycheck.dto.request.check.SearchSafetyCheckListRequest;
import com.smedi.ismedi.safetycheck.dto.response.check.SafetyCheckResponse;
import com.smedi.ismedi.web.starter.common.ResponseData;
import com.smedi.ismedi.web.starter.config.AsyncThreadPoolConfig;
import com.smedi.ismedi.web.starter.util.DozerUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
@Slf4j
public class TaskApplicationServiceImpl implements TaskApplicationService {
    private final DozerUtil dozerUtil;

    private final TaskDomainService taskDomainService;
    private final RemoteSmsNotificationFeignApi remoteSmsNotificationFeignApi;
    private final PersonRemoteApi personRemoteApi;
    private final RemotePersonCoreFeignApi remotePersonCoreFeignApi;
    private final ProjectAssignmentRemoteApiService projectAssignmentRemoteApiService;
    private final SafetyCheckRemoteApi safetyCheckRemoteApi;
    private final MessageApplicationService messageApplicationService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateTaskStatus(TaskRecordCommand taskRecordCommand) {
        TaskRecord taskRecord = dozerUtil.convertor(taskRecordCommand, TaskRecord.class);
        return taskDomainService.updateTaskRecord(taskRecord);
     /*   //查找需要更新的这条任务
        String oldStatus = "即将开始";
        List<TaskRecord> taskRecordReturn = taskDomainService.queryTaskByBySourceFromIdAndOldStatus(taskRecord.getSourceFromId(), oldStatus);

        Boolean flag = taskDomainService.updateTaskRecord(taskRecord);

        if (taskRecordCommand.getOldStatus().contains("即将开始") && taskRecordCommand.getTaskStatus().equals("进行中") && flag == true && taskRecordReturn != null && !taskRecordReturn.isEmpty()) {
            //发待处理短信 从“即将开始”变为“进行中
            for (TaskRecord taskRecord1 : taskRecordReturn) {
                SendSmsRequest dealSendSmsRequest = new SendSmsRequest();
                List<String> dealReceiverPhone = new ArrayList<>();
                List<String> dealParameters = new ArrayList<>();


                //receiverPhone.add(remotePersonCoreFeignApi.getQueryPersonInfo(taskRecord1.getDealPersonId()).getData().getMobile());
                dealReceiverPhone.add("13851582557");
                dealParameters.add(taskRecord1.getDealPersonName());

                dealParameters.add(taskRecord1.getProjectName());
                dealParameters.add(taskRecord1.getTaskName());
                dealParameters.add(taskRecord1.getTaskDescribe());
                //parameters.add(taskRecord1.getExpireTime().toString());
                dealParameters.add("2021-09-30 22:00:00");

                dealSendSmsRequest.setSmsTemplateId(1L)
                        .setReceivers(dealReceiverPhone)
                        .setParameters(dealParameters);

                ResponseData<Boolean> booleanResponseData = remoteSmsNotificationFeignApi.postSendShortMessage(dealSendSmsRequest);
                log.info("即将开始转为进行中时发短信提醒" + booleanResponseData.getData());
            }
        }
        return flag;*/
    }

    @Override
    public boolean updateTaskStatusRegularly() {
        return taskDomainService.updateTaskStatusRegularly();
    }

    @Override
    public boolean safetyCheckWeekly() {
        List<Long> projectRoles = new ArrayList<>();
        projectRoles.add(14L);
        projectRoles.add(16L);
        List<Long> organizationRoles = new ArrayList<>();
        organizationRoles.add(51L);
        organizationRoles.add(10L);
        organizationRoles.add(13L);

        // 获取周几
        int weekDay = LocalDate.now().getDayOfWeek().getValue();

        return safetyCheckWarn(projectRoles, organizationRoles, weekDay, "项目周检");
    }

    @Override
    public boolean safetyCheckMonthly() {
        List<String> safetyCheckTypes = new ArrayList<>();
        safetyCheckTypes.add("项目月检（主体院领导带班）");
        safetyCheckTypes.add("项目检查（主体院检查）");
        List<Long> organizationDepartmentRoles = new ArrayList<>();
        organizationDepartmentRoles.add(8L);

        // 获取今天几号
        int monthDay = LocalDateTime.now().getDayOfMonth();

        boolean flag1 = safetyCheckWarn(monthDay, safetyCheckTypes);
        boolean flag2 = safetyCheckWarn(new ArrayList<>(), organizationDepartmentRoles, monthDay, "项目检查（工程部检查）");

        return flag1 && flag2;
    }

    @Override
    public Boolean deleteHistoryTask() {
        taskDomainService.deleteHistoryTask();
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TaskRecord addTask(TaskRecordCommand taskRecordCommand) {
        TaskRecord taskRecord = dozerUtil.convertor(taskRecordCommand, TaskRecord.class);
        if (taskRecord.getExpireTime() != null && taskRecord.getExpireTime().toLocalDate().isBefore(LocalDate.now()) && (!("已删除".equals(taskRecord.getTaskStatus()) && !"已完成".equals(taskRecord.getTaskStatus()) && !"已关闭".equals(taskRecord.getTaskStatus())))) {
            taskRecord.setTaskStatus("已逾期");
        }
        if (taskRecord.getTaskStatus().equals("进行中")) {
            //发代办短信
            SendSmsRequest dealSendSmsRequest = new SendSmsRequest();
            List<String> dealReceiverPhone = new ArrayList<>();
            List<String> dealParameters = new ArrayList<>();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            if (null != taskRecord.getDealPersonId() && null != remotePersonCoreFeignApi.getQueryPersonInfo(taskRecord.getDealPersonId()) && null != remotePersonCoreFeignApi.getQueryPersonInfo(taskRecord.getDealPersonId()).getData() && null != remotePersonCoreFeignApi.getQueryPersonInfo(taskRecord.getDealPersonId()).getData().getMobile()
                    && !remotePersonCoreFeignApi.getQueryPersonInfo(taskRecord.getDealPersonId()).getData().getMobile().isEmpty()) {
                dealReceiverPhone.add(remotePersonCoreFeignApi.getQueryPersonInfo(taskRecord.getDealPersonId()).getData().getMobile());
                //dealReceiverPhone.add("13800138000");
                //dealReceiverPhone.add("18616256383");
                dealParameters.add(taskRecord.getDealPersonName());
                dealParameters.add(taskRecord.getProjectName());
                dealParameters.add(taskRecord.getTaskName());
                dealParameters.add(taskRecord.getTaskDescribe());
                dealParameters.add(taskRecord.getExpireTime() != null ? taskRecord.getExpireTime().format(formatter) : null);
                //dealParameters.add("2021-09-30 22:00:00");

                dealSendSmsRequest.setSmsTemplateId(1L)
                        .setReceivers(dealReceiverPhone)
                        .setParameters(dealParameters);

                ResponseData<Boolean> booleanResponseData = remoteSmsNotificationFeignApi.postSendShortMessage(dealSendSmsRequest);
                log.info("增加任务为进行中时发短信提醒" + booleanResponseData.getData());

            }
            // 发抄送短信
            if (StringUtils.isNotBlank(taskRecord.getNoticePersonIds())) {
                SendSmsRequest noticeSendSmsRequest = new SendSmsRequest();
                Map<String, String> noticeReceiverPhoneAndPersonNameMap = new HashMap<>();

                String[] noticePersonIds = StringUtils.split(taskRecord.getNoticePersonIds(), ",");
                List<String> noticePersonIdList = (noticePersonIds != null && noticePersonIds.length > 0) ? Arrays.asList(noticePersonIds) : Collections.emptyList();

                for (String noticePersonId : noticePersonIdList) {
                    noticeReceiverPhoneAndPersonNameMap.put(remotePersonCoreFeignApi.getQueryPersonInfo(Long.parseLong(noticePersonId)).getData().getMobile(),
                            remotePersonCoreFeignApi.getQueryPersonInfo(Long.parseLong(noticePersonId)).getData().getLastName());

                }

                for (Map.Entry<String, String> noticeReceiverPhoneAndPersonName : noticeReceiverPhoneAndPersonNameMap.entrySet()) {
                    List<String> noticeReceiverPhone = new ArrayList<>();
                    List<String> noticeParameters = new ArrayList<>();

                    noticeReceiverPhone.add(noticeReceiverPhoneAndPersonName.getKey());
                    //noticeReceiverPhone.add("13800138000");
                    //noticeReceiverPhone.add("18616256383");
                    noticeParameters.add(noticeReceiverPhoneAndPersonName.getValue());

                    noticeParameters.add(taskRecord.getProjectName());
                    noticeParameters.add(taskRecord.getTaskName());
                    noticeParameters.add(taskRecord.getTaskDescribe());

                    noticeSendSmsRequest.setSmsTemplateId(3L)
                            .setReceivers(noticeReceiverPhone)
                            .setParameters(noticeParameters);

                    remoteSmsNotificationFeignApi.postSendShortMessage(noticeSendSmsRequest);
                }
            }
        }
        return taskDomainService.addTaskRecord(taskRecord);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteTaskList(List<Long> ids) {
        return taskDomainService.deleteTaskList(ids);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteTaskListBySources(List<TaskRecordCommand> taskRecordCommands) {
        List<TaskRecord> taskRecords = dozerUtil.convertor(taskRecordCommands, TaskRecord.class);
        return taskDomainService.deleteTaskListBySourceIds(taskRecords);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TaskRecord editTask(TaskRecordCommand taskRecordCommand) {
        TaskRecord taskRecord = dozerUtil.convertor(taskRecordCommand, TaskRecord.class);
        return taskDomainService.editTaskRecord(taskRecord);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<TaskRecord> readTaskList(List<Long> ids) {
        List<TaskRecord> taskRecords = taskDomainService.readTaskList(ids);
        taskRecords.stream().filter(x -> x.getExpireTime() != null && x.getExpireTime().toLocalDate().isBefore(LocalDate.now()) && ((!"已删除".equals(x.getTaskStatus()) && !"已完成".equals(x.getTaskStatus()) && !"已关闭".equals(x.getTaskStatus()))
        )).forEach(x -> x.setTaskStatus("已逾期"));
        return taskRecords;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TaskRecord readTaskDaily(TaskRecordCommand taskRecordCommand) {
        TaskRecord taskRecord = dozerUtil.convertor(taskRecordCommand, TaskRecord.class);
        TaskRecord taskRecordTemp = taskDomainService.readTaskDaily(taskRecord);
        if (taskRecordTemp.getExpireTime() != null && taskRecordTemp.getExpireTime().toLocalDate().isBefore(LocalDate.now()) &&
                ((!"已删除".equals(taskRecordTemp.getTaskStatus()) && !"已完成".equals(taskRecordTemp.getTaskStatus()) && !"已关闭".equals(taskRecordTemp.getTaskStatus()))
                )) {
            taskRecordTemp.setTaskStatus("已逾期");
        }
        return taskRecordTemp;
    }

    @Override
    public Boolean cancelTask(TaskRecordCommand taskRecordCommand) {
        TaskRecord taskRecord = dozerUtil.convertor(taskRecordCommand, TaskRecord.class);
        return taskDomainService.cancelTask(taskRecord);
    }

    private boolean sendShortMessage(List<PersonResponse> personResponses, String projectName, String type, Long smsTemplateId) {
        boolean a = true;
        for (PersonResponse personResponse : personResponses) {
            SendSmsRequest sendSmsRequest = new SendSmsRequest();
            List<String> parameters = new ArrayList<>();
            parameters.add(personResponse.getLastName());
            parameters.add(projectName);
            parameters.add(type);
            List<String> receiver = new ArrayList<>();
            receiver.add(personResponse.getMobile());
            sendSmsRequest.setSmsTemplateId(5L);
            sendSmsRequest.setParameters(parameters);
            sendSmsRequest.setReceivers(receiver);
            ResponseData<Boolean> responseData = remoteSmsNotificationFeignApi.postSendShortMessage(sendSmsRequest);
            a = a && responseData.getData();
        }
        return a;
    }

    private boolean sendMessage(List<PersonResponse> personResponses, ProjectBasicResponse projectBasicResponse, String safetyCheckType) {
        boolean flag = true;
        for (PersonResponse personResponse : personResponses) {
            List<MessageInfoCommand> commands = new ArrayList<>();
            List<Long> receiverIds = new ArrayList<>();
            MessageInfoCommand messageInfoCommand = new MessageInfoCommand();
            StringBuilder messageContent = new StringBuilder();
            messageContent.append(personResponse.getLastName());
            messageContent.append(",您好！");
            messageContent.append(projectBasicResponse.getProjectName());
            messageContent.append("本周（或本月）还未进行");
            messageContent.append(safetyCheckType);
            messageContent.append("，请尽快安排相关工作，谢谢！");
            messageInfoCommand.setMessageContent(messageContent.toString());
            messageInfoCommand.setMessageType("安全检查");
            messageInfoCommand.setMessageTitle("安全检查工作提醒");
            messageInfoCommand.setProjectId(projectBasicResponse.getProjectId().toString());
            messageInfoCommand.setProjectName(projectBasicResponse.getProjectName());
            messageInfoCommand.setSourceFrom("系统提醒");
            messageInfoCommand.setMessageContent(messageContent.toString());
            messageInfoCommand.setMessageContent(messageContent.toString());
            commands.add(messageInfoCommand);
            receiverIds.add(personResponse.getPersonId());
            List<MessageRecord> messageRecords = messageApplicationService.sendMessage(commands, receiverIds);
            flag = flag && !messageRecords.isEmpty();
        }

        return flag;
    }

    private boolean safetyCheckWarn(List<Long> projectRoles, List<Long> organizationRoles, int day, String safetyCheckType) {
        boolean flag = true;
        Long smsTemplateId;
        if (safetyCheckType.equals("项目周检")) {
            smsTemplateId = 5L;
        } else {
            smsTemplateId = 6L;
        }

        // 获取全部项目
        List<ProjectBasicResponse> projectBasicResponses = projectAssignmentRemoteApiService.queryAllProjectList();
        projectBasicResponses = projectBasicResponses.stream().filter(projectBasicResponse -> projectBasicResponse.getProjectStatus().equals("CONSTRUCTING")).collect(Collectors.toList());

        // 获取所需的安全检查
        List<SafetyCheckResponse> safetyCheckResponses = getSafetyCheckResponses(safetyCheckType, day);

        // 判断每个项目是否有该安全检查
        Map<Long, List<SafetyCheckResponse>> projectIdSafetyChecks = safetyCheckResponses.stream().collect(Collectors.groupingBy(safetyCheckResponse -> safetyCheckResponse.getPosition().getProjectId()));
        for (ProjectBasicResponse projectBasicResponse : projectBasicResponses) {
            List<SafetyCheckResponse> safetyChecksInProject = projectIdSafetyChecks.getOrDefault(projectBasicResponse.getProjectId(), new ArrayList<>());
            if (safetyChecksInProject.isEmpty()) {
                // 给项目上的人发短信及消息
                if (!projectRoles.isEmpty()) {
                    List<PersonResponse> personInProjectWithRoleIds = personRemoteApi.getPersonInProjectWithRoleIds(projectBasicResponse.getProjectId(), projectRoles);
                    if (!personInProjectWithRoleIds.isEmpty()) {
                        flag = sendShortMessage(personInProjectWithRoleIds, projectBasicResponse.getProjectName(), safetyCheckType, smsTemplateId) && flag;
                        flag = sendMessage(personInProjectWithRoleIds, projectBasicResponse, safetyCheckType) && flag;
                    }
                }

                // 给上级组织上的特定角色发短信及消息
                if (!organizationRoles.isEmpty()) {
                    List<PersonResponse> personInOrganizationWithRoleIds = personRemoteApi.getPersonInOrganizationWithRoleIds(projectBasicResponse.getHrOrganizationId(), organizationRoles);
                    if (!personInOrganizationWithRoleIds.isEmpty()) {
                        flag = sendShortMessage(personInOrganizationWithRoleIds, projectBasicResponse.getProjectName(), safetyCheckType, smsTemplateId) && flag;
                        boolean b = sendMessage(personInOrganizationWithRoleIds, projectBasicResponse, safetyCheckType);
                        flag = flag && b;
                    }
                    List<PersonResponse> personIn2OrganizationWithRoleIds = personRemoteApi.getPersonInOrganizationWithRoleIds(2L, organizationRoles);
                    // 如果是项目检查（工程部检查），就给工程部专业工程师
                    if (!personIn2OrganizationWithRoleIds.isEmpty() && safetyCheckType.equals("项目检查（工程部检查）")) {
                        flag = flag && sendShortMessage(personIn2OrganizationWithRoleIds, projectBasicResponse.getProjectName(), safetyCheckType, smsTemplateId);
                        flag = flag && sendMessage(personIn2OrganizationWithRoleIds, projectBasicResponse, safetyCheckType);
                    }
                }

            }
        }

        return flag;
    }

    private boolean safetyCheckWarn(int day, List<String> safetyCheckTypes) {
        boolean flag = true;

        Long smsTemplateId;
        if (safetyCheckTypes.contains("项目周检")) {
            smsTemplateId = 5L;
        } else {
            smsTemplateId = 6L;
        }

        List<Long> organizationRoles = new ArrayList<>();
        organizationRoles.add(10L);
        organizationRoles.add(11L);

        List<Long> organizationLeaderRoles = new ArrayList<>();
        organizationLeaderRoles.add(10L);
        organizationLeaderRoles.add(13L);

        // 获取全部项目
        List<ProjectBasicResponse> projectBasicResponses = projectAssignmentRemoteApiService.queryAllProjectList();
        projectBasicResponses = projectBasicResponses.stream().filter(projectBasicResponse -> projectBasicResponse.getProjectStatus().equals("CONSTRUCTING")).collect(Collectors.toList());

        // 获取所需的安全检查
        List<SafetyCheckResponse> safetyCheckResponses = getSafetyCheckResponses(safetyCheckTypes, day);

        // 判断每个项目是否有该安全检查
        Map<Long, List<SafetyCheckResponse>> projectIdSafetyChecks = safetyCheckResponses.stream().collect(Collectors.groupingBy(safetyCheckResponse -> safetyCheckResponse.getPosition().getProjectId()));
        for (ProjectBasicResponse projectBasicResponse : projectBasicResponses) {
            List<SafetyCheckResponse> safetyChecksInProject = projectIdSafetyChecks.getOrDefault(projectBasicResponse.getProjectId(), new ArrayList<>());
            if (safetyChecksInProject.isEmpty()) {
                // 给上级组织上的特定角色发短信及消息
                if (!organizationRoles.isEmpty()) {
                    List<PersonResponse> personInOrganizationWithRoleIds = personRemoteApi.getPersonInOrganizationWithRoleIds(projectBasicResponse.getHrOrganizationId(), organizationRoles);
                    flag = flag && sendShortMessage(personInOrganizationWithRoleIds, projectBasicResponse.getProjectName(), safetyCheckTypes.get(0), smsTemplateId);
                    flag = flag && sendMessage(personInOrganizationWithRoleIds, projectBasicResponse, safetyCheckTypes.get(0));
                }
            }
            SafetyCheckResponse safetyCheckType0 = safetyChecksInProject.stream().filter(safetyCheckResponse -> safetyCheckResponse.getSafetyCheckType().equals(safetyCheckTypes.get(1))).findFirst().orElse(null);
            if (safetyChecksInProject.isEmpty() && null == safetyCheckType0) {
                // 给上级组织上的特定角色发短信及消息
                if (!organizationRoles.isEmpty()) {
                    List<PersonResponse> personInOrganizationWithRoleIds = personRemoteApi.getPersonInOrganizationWithRoleIds(projectBasicResponse.getHrOrganizationId(), organizationLeaderRoles);
                    flag = sendShortMessage(personInOrganizationWithRoleIds, projectBasicResponse.getProjectName(), safetyCheckTypes.get(1), smsTemplateId);
                    flag = flag && sendMessage(personInOrganizationWithRoleIds, projectBasicResponse, safetyCheckTypes.get(1));
                }
                return flag;
            }
        }

        return flag;
    }

    private List<SafetyCheckResponse> getSafetyCheckResponses(String safetyCheckType, int day) {
        // 获取时间
        String checkStartTime = LocalDateTime.now().minusDays(day - 1L).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        String checkEndTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));

        // 获取时间内安全检查
        SearchSafetyCheckListRequest searchSafetyCheckListRequest = new SearchSafetyCheckListRequest();
        searchSafetyCheckListRequest.setCheckStartTime(checkStartTime);
        searchSafetyCheckListRequest.setCheckEndTime(checkEndTime);
        searchSafetyCheckListRequest.setSafetyCheckType(safetyCheckType);
        return safetyCheckRemoteApi.searchSafetyCheckList(searchSafetyCheckListRequest);
    }

    private List<SafetyCheckResponse> getSafetyCheckResponses(List<String> safetyCheckTypes, int day) {
        // 获取时间
        String checkStartTime = LocalDateTime.now().minusDays(day - 1L).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        String checkEndTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));

        // 获取时间内安全检查
        SearchSafetyCheckListRequest searchSafetyCheckListRequest = new SearchSafetyCheckListRequest();
        searchSafetyCheckListRequest.setCheckStartTime(checkStartTime);
        searchSafetyCheckListRequest.setCheckEndTime(checkEndTime);
        searchSafetyCheckListRequest.setSafetyCheckTypes(safetyCheckTypes);
        return safetyCheckRemoteApi.searchSafetyCheckList(searchSafetyCheckListRequest);
    }
}
